﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Windows.Forms;
using System.Threading;
using System.Windows.Forms;

namespace _7DaysToDieTools.Class
{
    public class StackAction
    {
        static string FPathItems = Sinfo.Path.Config+Sinfo.File.Items;
        static string FPathBlocks = Sinfo.Path.Config+Sinfo.File.Blocks;
        /// <summary>
        /// 加载所有物品与方块数据
        /// </summary>
        /// <returns>返回获取的列表数据</returns>
        public static List<StackItem> LoadStackItems()
        {
            Dictionary<string, string> Langs = new Dictionary<string, string>();
            List<StackItem> StackItems = new List<StackItem>();
            StackItem sti = null;
            XmlDocument xDoc = null;
            XmlElement xe = null;
            string tmp = "";

            using (CsvFileReader CFR = new CsvFileReader(Sinfo.Path.Lang + Sinfo.File.Localization))
            {
                CsvRow cr = new CsvRow();
                CFR.ReadRow(cr);//过滤第一行标题

                while (CFR.ReadRow(cr))
                {
                    if (Langs.Keys.FirstOrDefault(X => X == cr[0].ToString()) != null) continue;
                    Langs.Add(cr[0].ToString(), cr[4].ToString());
                }
            }

            //所有物品
            xDoc = new XmlDocument();
            xDoc.Load(FPathItems);
            XmlElement xeItem = xDoc.SelectSingleNode("/items") as XmlElement;
            foreach (var item in xeItem.ChildNodes)
            {
                if (item.GetType() == typeof(XmlComment))
                {
                    continue;
                }
                xe = item as XmlElement;
                sti = new StackItem();
                sti.Stacktype = StackType.Item;
                sti.ID = xe.GetAttribute("id");
                sti.IDName = xe.GetAttribute("name");
                tmp = "";
                if(Langs.TryGetValue(sti.IDName,out tmp))
                {
                    sti.Name = tmp;
                }
                else
                {
                    sti.Name = sti.IDName;
                }
                xe=xe.SelectSingleNode("/items/item[@id='"+sti.ID+ "']/property[@name='Stacknumber']") as XmlElement;
                if(xe == null)
                {
                    sti.StackNum = "0";
                }
                else
                {
                    sti.StackNum = xe.GetAttribute("value");
                }
                StackItems.Add(sti);
            }
            //所有方块
            xDoc = new XmlDocument();
            xDoc.Load(FPathBlocks);
            XmlElement xeBlock = xDoc.SelectSingleNode("/blocks") as XmlElement;
            foreach (var item in xeBlock.ChildNodes)
            {
                if (item.GetType() == typeof(XmlComment))
                {
                    continue;
                }
                xe = item as XmlElement;
                sti = new StackItem();
                sti.Stacktype = StackType.Block;
                sti.ID= xe.GetAttribute("id");
                sti.IDName = xe.GetAttribute("name");
                tmp = "";
                if(Langs.TryGetValue(sti.IDName,out tmp))
                {
                    sti.Name = tmp;
                }
                else
                {
                    sti.Name = sti.IDName;
                }
                xe = xe.SelectSingleNode("/blocks/block[@id='" + sti.ID + "']/property[@name='Stacknumber']") as XmlElement;
                if (xe == null)
                {
                    sti.StackNum = "0";
                }
                else
                {
                    sti.StackNum = xe.GetAttribute("value");
                }
                StackItems.Add(sti);
            }
            return StackItems;
        }

        /// <summary>
        /// 保存所有物品与方块的叠加设置
        /// </summary>
        /// <param name="StackItems">修改后的列表</param>
        /// <param name="Msg">返回信息</param>
        /// <returns>是否保存成功</returns>
        public static bool SaveStackItems(List<StackItem> StackItems,out string Msg)
        {
            Msg = "";
            try
            {
                //变量
                XmlDocument xDoc = null;
                XmlElement xe = null;
                XmlTextWriter xw = null;

                //保存Items
                xDoc = new XmlDocument();
                xDoc.Load(FPathItems);
                foreach (StackItem item in StackItems)
                {
                    if (item.Stacktype == StackType.Block)
                    {
                        continue;
                    }
                    xe = xDoc.SelectSingleNode("/items/item[@id='" + item.ID + "']/property[@name='Stacknumber']") as XmlElement;
                    if (xe == null)
                    {
                        continue;
                    }
                    if (xe.GetAttribute("value") == item.StackNum)
                    {
                        continue;
                    }
                    xe.SetAttribute("value", item.StackNum);
                }
                xw = new XmlTextWriter(FPathItems, new UTF8Encoding(false));
                xw.Formatting = Formatting.Indented;
                xDoc.Save(xw);
                xw.Close();


                //保存Blocks
                xDoc = new XmlDocument();
                xDoc.Load(FPathBlocks);
                foreach (StackItem item in StackItems)
                {
                    if (item.Stacktype == StackType.Item)
                    {
                        continue;
                    }
                    xe = xDoc.SelectSingleNode("/blocks/block[@id='" + item.ID + "']/property[@name='Stacknumber']") as XmlElement;
                    if (xe == null)
                    {
                        continue;
                    }
                    if (xe.GetAttribute("value") == item.StackNum)
                    {
                        continue;
                    }
                    xe.SetAttribute("value", item.StackNum);
                }
                xw = new XmlTextWriter(FPathBlocks, new UTF8Encoding(false));
                xw.Formatting = Formatting.Indented;
                xDoc.Save(xw);
                xw.Close();

                return true;
            }
            catch(Exception x)
            {
                Msg = x.Message;
                return false;
            }
        }

        /// <summary>
        /// 获取指定类型文件的名称与叠加数列表
        /// </summary>
        /// <param name="sType">文件类型</param>
        /// <param name="filePath">文件路径</param>
        /// <returns>返回Dictionary<></returns>
        public static Dictionary<string, string> LoadStackNum(StackType sType, string filePath)
        {
            XmlElement xe = null;
            XmlElement xeItem = null;
            string tmp = "";
            Dictionary<string, string> dSS = new Dictionary<string, string>();
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(filePath);
            if (sType == StackType.Item)
            {
                xeItem = xDoc.SelectSingleNode("/items") as XmlElement;
                foreach (var item in xeItem.ChildNodes)
                {
                    if (item.GetType() == typeof(XmlComment)) continue;
                    xe = item as XmlElement;
                    tmp = xe.GetAttribute("name");
                    xe = xe.SelectSingleNode("/items/item[@name='" + tmp + "']/property[@name='Stacknumber']") as XmlElement;
                    if (xe == null) continue;
                    dSS.Add(tmp, xe.GetAttribute("value"));
                }
            }
            else
            {
                xeItem = xDoc.SelectSingleNode("/blocks") as XmlElement;
                foreach (var item in xeItem.ChildNodes)
                {
                    if (item.GetType() == typeof(XmlComment)) continue;
                    xe = item as XmlElement;
                    tmp = xe.GetAttribute("name");
                    xe = xe.SelectSingleNode("/blocks/block[@name='" + tmp + "']/property[@name='Stacknumber']") as XmlElement;
                    if (xe == null) continue;
                    dSS.Add(tmp, xe.GetAttribute("value"));
                }
            }
            return dSS;
        }

        /// <summary>
        /// 使用指定文件的叠加应用到目标文件
        /// </summary>
        /// <param name="SPath">源文件路径</param>
        /// <param name="DPath">目标文件路径</param>
        /// <param name="fileType">文件类型</param>

        public static void ApplyStack(string SPath,string DPath,StackType fileType)
        {
            XmlDocument xDoc = null;
            XmlElement xE = null;
            XmlElement xE1 = null;
            string tmp = "";
            Dictionary<string, string> Dics = LoadStackNum(fileType, SPath);
            xDoc = new XmlDocument();
            xDoc.Load(DPath);
            switch (fileType)
            {
                case StackType.Item:
                    foreach (var item in xDoc.SelectSingleNode("/items"))
                    {
                        if (item.GetType() == typeof(XmlComment)) continue;
                        xE = (XmlElement)item;
                        if (Dics.TryGetValue(xE.GetAttribute("name"), out tmp))
                        {
                            xE1 = xDoc.SelectSingleNode("/items/item[@name='" + xE.GetAttribute("name") + "']/property[@name='Stacknumber']") as XmlElement;
                            if (xE1.GetAttribute("value") == tmp) continue;
                            xE1.SetAttribute("value", tmp);
                        }
                    }
                    break;
                case StackType.Block:
                    foreach (var item in xDoc.SelectSingleNode("/blocks"))
                    {
                        if (item.GetType() == typeof(XmlComment)) continue;
                        xE = (XmlElement)item;
                        if (Dics.TryGetValue(xE.GetAttribute("name"), out tmp))
                        {
                            xE1 = xDoc.SelectSingleNode("/blocks/block[@name='" + xE.GetAttribute("name") + "']/property[@name='Stacknumber']") as XmlElement;
                            if (xE1.GetAttribute("value") == tmp) continue;
                            xE1.SetAttribute("value", tmp);
                        }
                    }
                    break;
            }
            XmlTextWriter xtw = new XmlTextWriter(DPath, new UTF8Encoding(false));
            xtw.Formatting = Formatting.Indented;
            xDoc.Save(xtw);
            xtw.Close();
        }

        /// <summary>
        /// 获取指定名称的叠加的网络数据文件名
        /// </summary>
        /// <param name="stackName">叠加名称</param>
        /// <returns></returns>
        public static string GetStackFile(string StackName)
        {
            NetConfig.GetConfig(true);
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(Sinfo.Data.BasePath + Sinfo.Net.File.Config);
            XmlElement xe = xDoc.SelectSingleNode("/config/stacks/stack[@name='" + StackName + "']") as XmlElement;
            if (xe == null) return "";
            return xe.InnerText;
        }

        /// <summary>
        /// 加载叠加选择框列表
        /// </summary>
        /// <param name="cbox">叠加选择框</param>
        public static void LoadStackList(ComboBox cbox)
        {
            cbox.Items.Clear();
            cbox.Items.Add("[本地]默认叠加");
            cbox.Items.Add("[本地]5000叠加");
            foreach (var item in GetNetStackList())
            {
                cbox.Items.Add("[网络]" + item.ToString());
            }
        }

        /// <summary>
        /// 获取网上叠加设置列表
        /// </summary>
        /// <returns></returns>
        public static List<string> GetNetStackList()
        {
            NetConfig.GetConfig(true);

            List<string> listStacks = new List<string>();
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(Sinfo.Data.BasePath + Sinfo.Net.File.Config);
            foreach (var item in xDoc.SelectSingleNode("/config/stacks").ChildNodes)
            {
                XmlElement xe = item as XmlElement;
                listStacks.Add(xe.GetAttribute("name"));
            }
            return listStacks;
        }

        /// <summary>
        /// 使用指定ZIP文件设置叠加
        /// </summary>
        public static void SetStack()
        {
            if (File.Exists(Sinfo.Data.Stack + Sinfo.File.Items))
            {
                ApplyStack(Sinfo.Data.Stack + Sinfo.File.Items, Sinfo.Path.Config + Sinfo.File.Items, StackType.Item);
            }
            if (File.Exists(Sinfo.Data.Stack + Sinfo.File.Blocks))
            {
                ApplyStack(Sinfo.Data.Stack + Sinfo.File.Blocks, Sinfo.Path.Config + Sinfo.File.Blocks, StackType.Block);
            }
        }

        public static void GetStackDefault()
        {
            if (Directory.Exists(Sinfo.Data.Stack)) Directory.Delete(Sinfo.Data.Stack, true);
            Directory.CreateDirectory(Sinfo.Data.Stack);
            File.WriteAllBytes(Sinfo.Data.Stack + "xxx.zip", Files.StackDefault);
            using(FileStream fs = File.Open(Sinfo.Data.Stack + "xxx.zip", FileMode.Open))
            {
                ZipAction.UnzipDatas(fs, Sinfo.Data.Stack);
            }
        }
        public static void GetStackMore()
        {
            if (Directory.Exists(Sinfo.Data.Stack)) Directory.Delete(Sinfo.Data.Stack, true);
            Directory.CreateDirectory(Sinfo.Data.Stack);
            File.WriteAllBytes(Sinfo.Data.Stack + "xxx.zip", Files.Stack5000);
            using (FileStream fs = File.Open(Sinfo.Data.Stack + "xxx.zip", FileMode.Open))
            {
                ZipAction.UnzipDatas(fs, Sinfo.Data.Stack);
            }
        }

        public static void GetStackNet(string StackName)
        {
            if (Directory.Exists(Sinfo.Data.Stack)) Directory.Delete(Sinfo.Data.Stack, true);
            Directory.CreateDirectory(Sinfo.Data.Stack);
            string fileName= GetStackFile(StackName);
            string netPath = Sinfo.Net.Stack + fileName;
            //下载
            new FormDown(null, new List<string>() { netPath }).ShowDialog();
            //移动并重命名
            File.Move(Sinfo.Data.BasePath + fileName, Sinfo.Data.Stack + "xxx.zip");
            using (FileStream fs = File.Open(Sinfo.Data.Stack + "xxx.zip", FileMode.Open))
            {
                ZipAction.UnzipDatas(fs, Sinfo.Data.Stack);
            }

        }


    }
}
